<!-- 
奇奇怪怪的表格
 可编辑的表格
 -->
<template>
  <ContainerLayout class="resource-management">
    <div class="form-container">
      <el-form ref="formRef" :inline="true" :model="queryForm" class="query-form" label-width="40px">
        <el-form-item label="部门" v-if="false">
          <el-cascader :options="deptList" :props="deptProps" style="width: 290px" v-model="queryForm.deptIds" collapse-tags clearable />
        </el-form-item>
        <el-form-item label="项目" v-if="false">
          <el-select v-model="projectValue" placeholder="请选择项目" style="width: 180px" :max-collapse-tags="1" multiple clearable collapse-tags>
            <template #header>
              <el-checkbox v-model="checkAllProject" :indeterminate="indeterminateProject" @change="handleCheckAllProject">全部</el-checkbox>
            </template>
            <el-option v-for="item in projectList" :key="item.code" :label="`${item.code}-${item.cname}`" :value="item.id" />
          </el-select>
        </el-form-item>
        <TimeSlotDatePicker label="时段" v-model="queryForm.date" />
        <el-form-item>
          <el-button type="primary" @click="handleClickBtnSubmit" :icon="Search">查询</el-button>
          <el-button @click="handleClickBtnReset" :icon="Refresh">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="table-container" ref="tableContainer">
      <el-scrollbar :height="scrollbarHeight" always>
        <div class="table-wrap" ref="tableWrap">
          <el-table ref="dataTable" :data="tableData" :height="tableHeight" style="width: 100%" border scrollbar-always-on :summary-method="getSummaries" header-cell-class-name="table-header-row" empty-text="没有数据">
            <el-table-column prop="parentDeptName" label="地区" width="120" fixed />
            <el-table-column prop="deptName" label="部门" width="150" fixed />
            <el-table-column prop="userNick" label="用户" width="120" fixed />
            <el-table-column label="Total" width="120" fixed>
              <template #default="scope">
                {{ rotTotal(scope.row) }}
              </template>
            </el-table-column>
            <el-table-column label="成本归属">
              <el-table-column v-for="(item, index) in tableColumnDate" :prop="item.label" :key="index" width="170" resizable>
                <template #header>
                  {{ item.label }}
                </template>
                <template #default="scope">
                  {{ getTableColValueByRow(scope.row, item) }}
                </template>
              </el-table-column>
            </el-table-column>
            <el-table-column></el-table-column>
          </el-table>
        </div>
      </el-scrollbar>
    </div>
  </ContainerLayout>
  <DialogUpdateHeadcountByProject ref="dialogUpdateHeadcountByProjectRef" @submited="handlerDialogUpdateSubmited" />
</template>
<script lang="ts" setup>
import ContainerLayout from '../layout/ContainerLayout.vue'
import DialogUpdateHeadcountByProject from '../components/dialog/DialogUpdateHeadcountByProject.vue'
import TimeSlotDatePicker from '../layout/FormTableLayout/TimeSlotDatePicker.vue'
import { reactive, ref, onMounted, h, nextTick } from 'vue'
import { useDeptStore, useTaskTypeStore, useProjectssStore } from '../stores'
import IProjectTypes from '../interface/IProjectTypes'
import { type CheckboxValueType } from 'element-plus'
// import { ElMessage } from 'element-plus'
import { Refresh, Search } from '@element-plus/icons-vue'
import * as utils from '../utils'
import http from '../http'

const tableWrap = ref<HTMLElement | null>(null)

const dialogUpdateHeadcountByProjectRef = ref<InstanceType<typeof DialogUpdateHeadcountByProject>>()
const projectssStore = useProjectssStore()
const deptStore = useDeptStore()
const deptList = ref(deptStore.getAllState())
const deptProps = ref({ multiple: true, label: 'deptName', value: 'deptId' })
// 多选
const checkAllProject = ref(false)
const indeterminateProject = ref(false)
const projectValue = ref<CheckboxValueType[]>([])
// 项目列表
const projectList = ref<Array<{ id: number; code: string; cname: string }>>(projectssStore.getAllState() as any)
// 项目类型
const projectTypes = ref<IProjectTypes[]>(useTaskTypeStore().getAllState())
// 表格是否查询过
const isQueryed = ref(false)
const projectTitle = ref<string>('')
const tableColumnDate = ref<any[]>([])

// 表格列表
const tableList = ref<{ tableTitle: string; project: any; tableData: any[] }[]>([])
// 表格数据
const tableRows = ref<any[]>([])
const tableData = ref<any[]>([])
const sourceData = ref<any[]>([])
const tableContainer = ref(ref<HTMLElement | null>(null))
const scrollbarHeight = ref(400)
const tableHeight = ref(500)

const weeks = ref()
// 表单
const queryForm = reactive({
  user: '',
  projectId: '',
  date: [] as Date[],
  deptIds: [] as string[] | number[],
})

/**
 * 处理全选项目的逻辑
 *
 * @param val Checkbox 的值
 */
const handleCheckAllProject = (val: CheckboxValueType) => {
  indeterminateProject.value = false
  if (val) {
    projectValue.value = projectList.value.map((_) => _.id)
  } else {
    projectValue.value = []
  }
}

const handlerDialogUpdateSubmited = async () => {
  await handleClickBtnSubmit()
}
/**
 * 提交表单处理函数
 *
 * @returns {Promise<void>} 返回一个异步操作的Promise对象，无返回值
 */
const handleClickBtnSubmit = async () => {
  // console.log('queryForm', queryForm)
  isQueryed.value = true
  projectTitle.value = ''

  if (queryForm.date.length == 2) {
    const [start, end] = queryForm.date
    weeks.value = utils.getWeeksBetweenDates(start, end)

    //
    await getTableRow()
    await getTableData()
    await setTableColumn()

    // 部门列表
    await getDeptList()
    await buildDataTable()
  }
}

/**
 * 异步构建数据表格。
 *
 * @returns 无返回值。
 */
const buildDataTable = async () => {
  // console.log(JSON.stringify(tableRows.value))
  // console.log(JSON.stringify(tableColumnDate.value))

  const rowsResult = await getRequirementList()

  const tableData = await mergeData(tableRows.value, tableColumnDate.value)

  const items = projectList.value.filter((e: any) => {
    if (projectValue.value.includes(e.id)) {
      return e
    }
  })

  tableList.value = items.map((item: any) => {
    // console.log('item', item.id)
    // console.log('rowsResult', rowsResult)
    const rows = rowsResult.filter((e: any) => e.projectId == item.id)
    const newData = mergeLists(tableData, rows)
    return {
      tableTitle: `${item.code}-${item.cname}`,
      project: { ...item },
      tableData: newData,
    }
  })
  if (items.length > 0) {
    // // Remaining/Available 实际差额
    // tableList.value.push({
    //   tableTitle: 'Remaining/Available 实际差额',
    //   project: {
    //     isTotal: true,
    //   },
    //   tableData,
    // })

    // // Total Requirement 所有项目需求
    // await getTotalRequirement(tableData)

    // Total Headcount 人事总人数
    await getTotalHeadcount(tableData)
    await tableColumnColspan()
  }
}

const tableColumnColspan = () => {
  setTimeout(() => {
    const tableWrapElement = tableContainer.value
    if (tableWrapElement) {
      // 表格的最后一行前两个单元格合并
      const tableFooters = tableWrapElement.querySelectorAll('.el-table__footer')
      tableFooters.forEach((e: any) => {
        const tds = e.querySelectorAll('td')
        const tbs0 = tds[0] as HTMLElement
        tbs0.setAttribute('colspan', '2')
        tbs0.style.textAlign = 'center'
        tds[1].remove()
      })
    }
  }, 200)
}
/**
 * 合并两个列表
 *
 * @param list1 第一个列表
 * @param list2 第二个列表
 * @returns 合并后的列表
 */
const mergeLists = (list1: any, list2: any) => {
  return list1.map((item1: any) => {
    const matchingItems = list2.filter((item2: any) => item2.deptId === item1.deptId)
    const resultItem = { ...item1 }
    matchingItems.forEach((item2: any) => {
      const key = `${item2.weekStartDate} - ${item2.weekEndDate}`
      resultItem[key] = item2.weekUserNum
      resultItem[item2.weekStartDate] = item2.weekUserNum
      resultItem[item2.weekEndDate] = item2.weekUserNum
      resultItem[key + '|flag'] = item2.weekUserNum > 0 ? true : false
      resultItem[key + '|id'] = item2.id
    })
    return resultItem
  })
}

/**
 * 计算表格数据中的汇总信息
 *
 * @param param 包含表格列信息和数据的对象
 * @returns 返回汇总信息的数组，每个元素可能是字符串或VNode，表示该列的汇总结果
 */
const getSummaries = (param: any) => {
  const { columns, data } = param
  const sums: any[] = []
  columns.forEach((column: any, index: number) => {
    if (index === 0) {
      sums[index] = h('div', {}, ['Total Headcount'])
      return
    }
    const values = data.map((item: any) => Number(item[column.property]))
    // sums[index] = '0'
    if (!values.every((value: any) => Number.isNaN(value))) {
      sums[index] = values.reduce((prev: any, curr: any) => {
        const value = Number(curr)
        if (!Number.isNaN(value)) {
          return prev + curr
        } else {
          return prev
        }
      }, 0)
    } else {
      // console.log(index)
      sums[index] = ''
    }
  })
  sums[1] = ''
  return sums
}

/**
 * 合并数据函数
 *
 * @param a 第一个数据集合，包含多个部门对象
 * @param b 第二个数据集合，包含多个时间区间对象
 * @returns 合并后的数据集合，包含合并后的部门对象数组
 */
const mergeData = (a: any, b: any) => {
  // console.log('b', b)
  // console.log('tableColumnDate.value', tableColumnDate.value)
  const result: any[] = []
  // 遍历集合a中的每个部门对象
  a.forEach((department: any) => {
    const mergedObj = { ...department }
    // 遍历集合b中的每个时间区间对象
    b.forEach((timeRange: any) => {
      const { columnName, start, end } = timeRange
      // 将时间区间相关的属性添加到合并后的对象中，并初始化为0
      mergedObj[columnName] = 0
      mergedObj[start] = 0
      mergedObj[end] = 0
    })
    result.push(mergedObj)
  })
  return result
}
/**
 * 点击按钮重置表单
 *
 * 异步调用 resetForm 函数重置表单
 */
const handleClickBtnReset = async () => {
  await resetForm()
}

/**
 * 重置表单
 *
 * 重置查询表单的所有字段到初始状态，包括用户、项目ID、日期范围、部门ID数组和时间日志类别
 */
const resetForm = () => {
  isQueryed.value = false
  projectTitle.value = ''
  const [start, end] = utils.getDateRangeByDate(utils.shortcutsType.本月) as Date[]
  queryForm.user = ''
  queryForm.projectId = ''
  queryForm.date = [start, end]
  queryForm.deptIds = [] as string[] | number[]
  projectValue.value = []
  // handleClickBtnSubmit()
}
/**
 * Total Headcount 人事总人数
 *
 * @returns 无返回值
 */
const getTotalHeadcount = async (tableData: any) => {
  const rowsAll = await getRequirementList('listall')
  const newDataAll = mergeLists(tableData, rowsAll)
  tableList.value.push({
    tableTitle: '所有项目需求',
    project: {
      isTotal: true,
    },
    tableData: newDataAll,
  })
}

/**
 * 获取部门列表
 *
 * @returns 返回处理后的部门列表
 */
const getDeptList = async () => {
  const data = deptStore.getAllListState()
  const deptMap = new Map()
  const result: any = []

  // 先将所有部门信息存入Map，方便后续查找父部门名称
  data.forEach((item: any) => {
    deptMap.set(item.deptId, item)
  })

  data.forEach((item: any) => {
    const { deptId, parentId, deptName } = item
    const deptNamesExclude = '总经办,技术组'.split(',')
    if (parentId !== 100 && deptId !== 100 && deptNamesExclude.indexOf(deptName) === -1) {
      const parentItem = deptMap.get(parentId)
      const parentDeptName = parentItem.deptName
      result.push({ ...item, parentDeptName })
    }
  })

  tableRows.value = result
}
/**
 * 异步获取数据
 *
 * @returns 返回数据行
 */
const getRequirementList = async (type: 'list' | 'listall' = 'list') => {
  const rows = await httpGetDataRow({
    path: `/dev-api/oa/requirement/${type}`,
  })
  return rows
}
const httpGetDataRow = async (queryParams: any) => {
  const [first] = weeks.value
  const [last] = weeks.value.slice(-1)
  const startTimelogDate = utils.formatDate(first.start, 'yyyy-MM-dd')
  const endTimelogDate = utils.formatDate(last.end, 'yyyy-MM-dd')
  const defaultParams = {
    method: 'GET',
    path: ``,
    params: { pageSize: 99999, startTimelogDate, endTimelogDate },
  }
  Object.assign(defaultParams, queryParams)
  const res = await http(defaultParams)
  return res.rows
}

/**
 * 异步获取表格数据
 *
 * @returns 无返回值
 */
const getTableData = async () => {
  sourceData.value = await httpGetDataRow({
    path: `/dev-api/oa/timelog/listprojecttime/`,
  })
}
const rotTotal = (row: any) => {
  // console.log('row', row.userNick)

  const cnts: any = []
  sourceData.value.map((item: any) => {
    if (item.userNick == row.userNick) {
      cnts.push(item.durationTime)
    }
  })

  let sum = sumIntegerAndDecimalParts(cnts)

  if (sum <= 100.1 && sum >= 99.5) {
    sum = 100
  }

  // console.log('sourceData.value', cnts)
  return sum + '%'
}
const sumIntegerAndDecimalParts = (numbers: any[]) => {
  const integerSums: any = []
  const decimalSums: any = []
  numbers.forEach((num) => {
    const [integer, decimal] = num.toString().split('.')

    integerSums.push(integer)
    decimalSums.push(decimal ? '0.' + decimal : '0')
  })

  let integerSum = eval(integerSums.join('+'))
  let decimalSum = eval(decimalSums.join('+'))

  const totalSum = integerSum + decimalSum

  return isNaN(totalSum) ? 0 : totalSum
}

const getTableColValueByRow = (row: any, colItem: any) => {
  // console.log('row', row)
  // console.log('colItem', colItem.colId)
  let colValue = null
  if (colItem.timelogCategory == 0) {
    colValue = sourceData.value.find((item: any) => item.timelogCategory == 0 && item.projectId == colItem.colId && item.userNick == row.userNick)
  } else {
    colValue = sourceData.value.find((item: any) => item.timelogCategory == colItem.colId && item.userNick == row.userNick)
  }
  // const obj: any = {}
  // obj[row.userNick] = colValue ? colValue.durationTime : 0

  if (colValue) {
    return colValue.durationTime + '%'
  } else {
    return 0
  }
}

const getTableRow = async () => {
  const res = await httpGetDataRow({
    path: '/dev-api/oa/hrm/listbydept',
  })
  tableData.value = res
}

/**
 * 设置表格列
 *
 * @returns 无返回值
 */
const setTableColumn = async () => {
  // 设置 table 列
  tableColumnDate.value = []
  // 获取项目

  projectList.value.forEach((item: any) => {
    const { id, ename, cname } = item
    tableColumnDate.value.push({
      colId: id,
      label: cname,
      sublabel: ename,
      key: id,
      colType: 'Project',
      timelogCategory: 0,
    })
  })

  // 获取其他 列（请假，教学，………………）
  projectTypes.value.forEach((item: any) => {
    const { dictValue, dictLabel } = item
    if (dictValue * 1 !== 0) {
      tableColumnDate.value.push({
        colId: dictValue,
        label: dictLabel,
        sublabel: dictLabel,
        key: dictValue,
        colType: 'Other',
        timelogCategory: dictValue * 1,
      })
    }
  })
}

onMounted(async () => {
  await handleClickBtnReset()
  // console.log('projectList', queryForm.date)
  // http://192.168.98.177:8080/oa/timelog/listprojecttime?startTimelogDate=2024-12-01&endTimelogDate=2024-12-31&deptIds=103,224

  if (tableContainer.value) {
    scrollbarHeight.value = tableContainer.value.offsetHeight
  }
  nextTick(() => {
    const tableWrapElement = tableWrap.value
    if (tableWrapElement) {
      // 设置表格高度
      // tableHeight.value = tableWrapElement.offsetHeight
      tableHeight.value = scrollbarHeight.value
      // 延迟执行，等待表格渲染完成后再设置
      setTimeout(() => {
        if (tableWrapElement) {
          // 表格的最后一行前两个单元格合并
          const tds = tableWrapElement.querySelectorAll('.el-table__footer td')
          const tbs0 = tds[0] as HTMLElement
          if (tbs0) {
            tbs0.setAttribute('colspan', '2')
            tbs0.style.textAlign = 'center'
            tds[1].remove()
          }
        }
      }, 200)
    }
  })
})
</script>
<style lang="scss" scoped>
.resource-management {
  display: flex;
  flex-direction: column;
  .form-container {
    display: flex;
    justify-content: flex-start;
  }
  .table-container {
    flex: 1;
    display: flex;
    flex-direction: column;
    .table-wrap {
      flex: 1;
    }
  }
  .table-header-cell {
    writing-mode: vertical-lr;
    // line-height: 1;
  }
  .table-cell {
    cursor: pointer;
    width: 100%;
  }
}
</style>
